#include "locker.hpp"
#include "threadPool.hpp"
#include "http_conn.hpp"

#define MAX_FD 65536
#define MAX_EVENT_NUMBER 1024

int http_conn::m_user_cnt = 0;
int http_conn::m_epfd = -1;

void show_error(int confd, const char* info)
{
    printf("error: %s\n", info);
    send(confd, info, strlen(info), 0);
    close(confd);
}

//添加信号事件
void addSig(int sig, void (*handler)(int), bool restart = true)
{
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = handler;
    if (restart)
        act.sa_flags |= SA_RESTART;
    sigfillset(&act.sa_mask);
    assert(sigaction(sig, &act, NULL) != -1);
}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s port\n", argv[0]);
        return 1;
    }
    int port = atoi(argv[1]);
    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    
    //创建socket
    int listen_sock = socket(PF_INET, SOCK_STREAM, 0);
    assert(listen_sock != -1);
    //设置close关闭
    struct linger tmp = {1, 0};
    int ret = setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp));
    assert(ret != -1);
    //绑定socket
    ret = bind(listen_sock, (struct sockaddr*)&address, sizeof(address));
    assert(ret != -1);
    //监听socket
    ret = listen(listen_sock, 5);
    assert(ret != -1);

    //忽略SIGPIPE信号
    addSig(SIGPIPE, SIG_IGN);

    //创建epoll模型
    int epfd = epoll_create(5);
    assert(epfd != -1);
    http_conn::m_epfd = epfd;
    //将listen_sock添加到注册事件表
    addEvent(epfd, listen_sock, false);
    //创建epoll_wait就绪事件数组
    struct epoll_event* events = new struct epoll_event[MAX_EVENT_NUMBER];
    assert(events);

    //创建线程池
    threadPool<http_conn>* tp = new threadPool<http_conn>;
    assert(tp);

    //创建用户数组
    http_conn* users = new http_conn[MAX_FD];
    assert(users);

    //业务逻辑
    while (true)
    {
        int n = epoll_wait(http_conn::m_epfd, events, MAX_EVENT_NUMBER, -1);
        if (n < 0 && errno != EINTR)
        {
            printf("epoll_wait error\n");
            break;
        }

        for (int i = 0;i < n;i++)
        {
            int sockfd = events[i].data.fd;
            if (listen_sock == sockfd && (events[i].events & EPOLLIN))
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int sock = accept(sockfd, (struct sockaddr*)&client, &len);
                if (sock < 0)
                {
                    printf("accept sock failed\n");
                    continue;
                }
                if (http_conn::m_user_cnt >= MAX_FD)
                {
                    show_error(sock, "Internal server busy!");
                    continue;
                }
                users[sock].init(client, sock);
                printf("有新的连接到来 %d\n", sock);
            }
            else if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP))
                users[sockfd].close_conn();
            else if (events[i].events & EPOLLIN)
            {
                printf("有数据到达\n");
                if (users[sockfd].read_())
                    tp->append(users + sockfd);
                else
                    users[sockfd].close_conn();
            }
            else if (events[i].events & EPOLLOUT)
            {
                if (!users[sockfd].write_())
                {
                    users[sockfd].close_conn(true);
                }
            } 
            else
                continue;
        }
    }

    delete[] users;
    delete[] events;
    delete tp;
    close(http_conn::m_epfd);
    close(listen_sock);

    return 0;
}